/*
 * Wazuh Send report test
 * Copyright (C) 2015, Wazuh Inc.
 * May 12, 2024.
 *
 * This program is free software; you can redistribute it
 * and/or modify it under the terms of the GNU General Public
 * License (version 2) as published by the FSF - Free Software
 * Foundation.
 */

#include "globalSyncInventory_test.hpp"
#include "TrampolineIndexerConnector.hpp"
#include "TrampolineOsDataCache.hpp"
#include "flatbuffers/idl.h"
#include "flatbuffers/include/rsync_schema.h"
#include "globalSyncInventory.hpp"
#include "scanContext.hpp"

using ::testing::_;

namespace NSGlobalSyncInventoryTest
{
    const std::string SYNCHRONIZATION_INTEGRITY_GLOBAL_000_MSG =
        R"(
            {
                "agent_info": {
                    "agent_id": "000",
                    "agent_ip": "192.168.33.20",
                    "agent_name": "focal"
                },
                "data_type": "integrity_check_global",
                "data": {
                    "id": 1700236640,
                    "attributes_type": "syscollector_packages"
                }
            }
        )";

    const std::string SYNCHRONIZATION_INTEGRITY_GLOBAL_001_MSG =
        R"(
            {
                "agent_info": {
                    "agent_id": "001",
                    "agent_ip": "192.168.33.20",
                    "agent_name": "focal"
                },
                "data_type": "integrity_check_global",
                "data": {
                    "id": 1700236640,
                    "attributes_type": "syscollector_packages"
                }
            }
        )";

    // Helpers

    const Os osData {.hostName = "osdata_hostname",
                     .architecture = "osdata_architecture",
                     .name = "osdata_name",
                     .codeName = "osdata_codeName",
                     .majorVersion = "osdata_majorVersion",
                     .minorVersion = "osdata_minorVersion",
                     .patch = "osdata_patch",
                     .build = "osdata_build",
                     .platform = "osdata_platform",
                     .version = "osdata_version",
                     .release = "osdata_release",
                     .displayVersion = "osdata_displayVersion",
                     .sysName = "osdata_sysName",
                     .kernelVersion = "osdata_kernelVersion",
                     .kernelRelease = "osdata_kernelRelease"};

    void expectOsData()
    {
        spOsDataCacheMock = std::make_shared<MockOsDataCache>();
        EXPECT_CALL(*spOsDataCacheMock, getOsData(_, _))
            .WillOnce(testing::Invoke(
                [](const std::string&, Os& osDataResult)
                {
                    osDataResult = osData;
                    return true;
                }));
    }

} // namespace NSGlobalSyncInventoryTest

using namespace NSGlobalSyncInventoryTest;

/**
 * @brief Test the sync message with the agent 000 and cluster enabled.
 * In this case is expected to send the message to the indexer with the node name as prefix of the agent id.
 */
TEST_F(GlobalSyncInventoryTest, SyncMessageWithClusterEnabled)
{
    // Policy manager initialization.
    const auto& configJson {nlohmann::json::parse(R"({
        "vulnerability-detection": {
            "enabled": "yes",
            "index-status": "yes",
            "cti-url": "cti-url.com"
        },
        "osdataLRUSize":1000,
        "clusterName":"cluster01",
        "clusterNodeName":"node01",
        "clusterEnabled":true
        })")};

    PolicyManager::instance().initialize(configJson);

    spIndexerConnectorMock = std::make_shared<MockIndexerConnector>();
    EXPECT_CALL(*spIndexerConnectorMock, sync("node01_000")).Times(1);

    auto pIndexerConnectorTrap = std::make_shared<TrampolineIndexerConnector>();

    flatbuffers::Parser parser;
    ASSERT_TRUE(parser.Parse(rsync_SCHEMA));
    ASSERT_TRUE(parser.Parse(SYNCHRONIZATION_INTEGRITY_GLOBAL_000_MSG.c_str()));
    uint8_t* buffer = parser.builder_.GetBufferPointer();
    std::variant<const SyscollectorDeltas::Delta*, const Synchronization::SyncMsg*, const nlohmann::json*>
        syscollectorSynchronization = Synchronization::GetSyncMsg(reinterpret_cast<const char*>(buffer));
    auto scanContextOriginal = std::make_shared<TScanContext<TrampolineOsDataCache>>(syscollectorSynchronization);

    auto spGlobalSyncInventory =
        std::make_shared<TGlobalSyncInventory<TrampolineIndexerConnector, TScanContext<TrampolineOsDataCache>>>(
            pIndexerConnectorTrap);

    EXPECT_NO_THROW(spGlobalSyncInventory->handleRequest(scanContextOriginal));
    PolicyManager::instance().teardown();
}

/**
 * @brief Test the sync message with the agent 001 and cluster enabled.
 * In this case is expected to send the message to the indexer without the node name as prefix of the agent id.
 */
TEST_F(GlobalSyncInventoryTest, SyncMessageWithClusterEnabledWithoutNodeName)
{
    // Policy manager initialization.
    const auto& configJson {nlohmann::json::parse(R"({
        "vulnerability-detection": {
            "enabled": "yes",
            "index-status": "yes",
            "cti-url": "cti-url.com"
        },
        "osdataLRUSize":1000,
        "clusterName":"cluster01",
        "clusterEnabled":true
        })")};

    PolicyManager::instance().initialize(configJson);
    spIndexerConnectorMock = std::make_shared<MockIndexerConnector>();
    EXPECT_CALL(*spIndexerConnectorMock, sync("001")).Times(1);

    auto pIndexerConnectorTrap = std::make_shared<TrampolineIndexerConnector>();

    flatbuffers::Parser parser;
    ASSERT_TRUE(parser.Parse(rsync_SCHEMA));
    ASSERT_TRUE(parser.Parse(SYNCHRONIZATION_INTEGRITY_GLOBAL_001_MSG.c_str()));
    uint8_t* buffer = parser.builder_.GetBufferPointer();
    std::variant<const SyscollectorDeltas::Delta*, const Synchronization::SyncMsg*, const nlohmann::json*>
        syscollectorSynchronization = Synchronization::GetSyncMsg(reinterpret_cast<const char*>(buffer));
    auto scanContextOriginal = std::make_shared<TScanContext<TrampolineOsDataCache>>(syscollectorSynchronization);

    auto spGlobalSyncInventory =
        std::make_shared<TGlobalSyncInventory<TrampolineIndexerConnector, TScanContext<TrampolineOsDataCache>>>(
            pIndexerConnectorTrap);

    EXPECT_NO_THROW(spGlobalSyncInventory->handleRequest(scanContextOriginal));
    PolicyManager::instance().teardown();

    spIndexerConnectorMock.reset();
}
